/**
 * 图片相关工具函数
 */

/**
 * 支持的图片类型
 */
export const SUPPORTED_IMAGE_TYPES = [
  'jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg', 'ico'
]

/**
 * 图片MIME类型映射
 */
export const IMAGE_MIME_TYPES = {
  'jpg': 'image/jpeg',
  'jpeg': 'image/jpeg',
  'png': 'image/png',
  'gif': 'image/gif',
  'bmp': 'image/bmp',
  'webp': 'image/webp',
  'svg': 'image/svg+xml',
  'ico': 'image/x-icon'
}

/**
 * 检查文件是否为图片
 * @param {File|string} file - 文件对象或文件名
 * @returns {boolean}
 */
export function isImage(file) {
  if (typeof file === 'string') {
    // 如果是字符串，检查文件扩展名
    const ext = getFileExtension(file)
    return SUPPORTED_IMAGE_TYPES.includes(ext)
  }
  
  if (file && file.type) {
    // 如果是文件对象，检查MIME类型
    return file.type.startsWith('image/')
  }
  
  return false
}

/**
 * 获取文件扩展名
 * @param {string} filename - 文件名
 * @returns {string}
 */
export function getFileExtension(filename) {
  if (!filename) return ''
  const lastDotIndex = filename.lastIndexOf('.')
  if (lastDotIndex === -1) return ''
  return filename.substring(lastDotIndex + 1).toLowerCase()
}

/**
 * 验证图片类型
 * @param {File} file - 文件对象
 * @param {Array} allowedTypes - 允许的类型数组
 * @returns {Object} - { valid: boolean, message: string }
 */
export function validateImageType(file, allowedTypes = SUPPORTED_IMAGE_TYPES) {
  if (!file) {
    return { valid: false, message: '文件不能为空' }
  }
  
  const ext = getFileExtension(file.name)
  
  if (!isImage(file)) {
    return { valid: false, message: '文件不是有效的图片格式' }
  }
  
  if (!allowedTypes.includes(ext)) {
    return { 
      valid: false, 
      message: `不支持的图片格式，仅支持：${allowedTypes.join('、')}` 
    }
  }
  
  return { valid: true, message: '' }
}

/**
 * 验证图片大小
 * @param {File} file - 文件对象
 * @param {number} maxSize - 最大大小（MB）
 * @returns {Object} - { valid: boolean, message: string }
 */
export function validateImageSize(file, maxSize = 10) {
  if (!file) {
    return { valid: false, message: '文件不能为空' }
  }
  
  const maxBytes = maxSize * 1024 * 1024
  
  if (file.size > maxBytes) {
    return { 
      valid: false, 
      message: `图片大小不能超过 ${maxSize}MB，当前大小：${formatFileSize(file.size)}` 
    }
  }
  
  return { valid: true, message: '' }
}

/**
 * 格式化文件大小
 * @param {number} bytes - 字节数
 * @returns {string}
 */
export function formatFileSize(bytes) {
  if (bytes === 0) return '0 B'
  
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

/**
 * 生成图片预览URL
 * @param {File} file - 文件对象
 * @returns {Promise<string>}
 */
export function generateImagePreview(file) {
  return new Promise((resolve, reject) => {
    if (!isImage(file)) {
      reject(new Error('文件不是有效的图片格式'))
      return
    }
    
    const reader = new FileReader()
    reader.onload = (e) => resolve(e.target.result)
    reader.onerror = () => reject(new Error('读取文件失败'))
    reader.readAsDataURL(file)
  })
}

/**
 * 获取图片信息（尺寸等）
 * @param {File|string} file - 文件对象或图片URL
 * @returns {Promise<Object>}
 */
export function getImageInfo(file) {
  return new Promise((resolve, reject) => {
    const img = new Image()
    
    img.onload = () => {
      resolve({
        width: img.naturalWidth,
        height: img.naturalHeight,
        aspectRatio: img.naturalWidth / img.naturalHeight
      })
    }
    
    img.onerror = () => {
      reject(new Error('获取图片信息失败'))
    }
    
    if (typeof file === 'string') {
      img.src = file
    } else if (file instanceof File) {
      generateImagePreview(file).then(url => {
        img.src = url
      }).catch(reject)
    } else {
      reject(new Error('无效的文件类型'))
    }
  })
}

/**
 * 压缩图片
 * @param {File} file - 图片文件
 * @param {Object} options - 压缩选项
 * @returns {Promise<File>}
 */
export function compressImage(file, options = {}) {
  const {
    maxWidth = 1920,
    maxHeight = 1080,
    quality = 0.8,
    type = 'image/jpeg'
  } = options
  
  return new Promise((resolve, reject) => {
    if (!isImage(file)) {
      reject(new Error('文件不是有效的图片格式'))
      return
    }
    
    const canvas = document.createElement('canvas')
    const ctx = canvas.getContext('2d')
    const img = new Image()
    
    img.onload = () => {
      // 计算压缩后的尺寸
      let { width, height } = img
      
      if (width > maxWidth) {
        height = (height * maxWidth) / width
        width = maxWidth
      }
      
      if (height > maxHeight) {
        width = (width * maxHeight) / height
        height = maxHeight
      }
      
      canvas.width = width
      canvas.height = height
      
      // 绘制压缩后的图片
      ctx.drawImage(img, 0, 0, width, height)
      
      // 转换为Blob
      canvas.toBlob((blob) => {
        if (blob) {
          const compressedFile = new File([blob], file.name, {
            type: type,
            lastModified: Date.now()
          })
          resolve(compressedFile)
        } else {
          reject(new Error('图片压缩失败'))
        }
      }, type, quality)
    }
    
    img.onerror = () => {
      reject(new Error('图片加载失败'))
    }
    
    generateImagePreview(file).then(url => {
      img.src = url
    }).catch(reject)
  })
}

/**
 * 批量验证图片
 * @param {Array<File>} files - 文件数组
 * @param {Object} options - 验证选项
 * @returns {Object} - { valid: Array, invalid: Array }
 */
export function validateImages(files, options = {}) {
  const {
    allowedTypes = SUPPORTED_IMAGE_TYPES,
    maxSize = 10,
    maxCount = 10
  } = options
  
  const valid = []
  const invalid = []
  
  // 检查数量限制
  if (files.length > maxCount) {
    return {
      valid: [],
      invalid: files.map(file => ({
        file,
        errors: [`超出最大上传数量限制（${maxCount}张）`]
      }))
    }
  }
  
  files.forEach(file => {
    const errors = []
    
    // 验证类型
    const typeValidation = validateImageType(file, allowedTypes)
    if (!typeValidation.valid) {
      errors.push(typeValidation.message)
    }
    
    // 验证大小
    const sizeValidation = validateImageSize(file, maxSize)
    if (!sizeValidation.valid) {
      errors.push(sizeValidation.message)
    }
    
    if (errors.length === 0) {
      valid.push(file)
    } else {
      invalid.push({ file, errors })
    }
  })
  
  return { valid, invalid }
}

/**
 * 创建图片缩略图
 * @param {File|string} source - 图片文件或URL
 * @param {Object} options - 缩略图选项
 * @returns {Promise<string>}
 */
export function createThumbnail(source, options = {}) {
  const {
    width = 150,
    height = 150,
    quality = 0.8,
    type = 'image/jpeg'
  } = options
  
  return new Promise((resolve, reject) => {
    const canvas = document.createElement('canvas')
    const ctx = canvas.getContext('2d')
    const img = new Image()
    
    img.onload = () => {
      canvas.width = width
      canvas.height = height
      
      // 计算居中裁剪的位置
      const scale = Math.max(width / img.width, height / img.height)
      const scaledWidth = img.width * scale
      const scaledHeight = img.height * scale
      const x = (width - scaledWidth) / 2
      const y = (height - scaledHeight) / 2
      
      ctx.drawImage(img, x, y, scaledWidth, scaledHeight)
      
      const thumbnailUrl = canvas.toDataURL(type, quality)
      resolve(thumbnailUrl)
    }
    
    img.onerror = () => {
      reject(new Error('生成缩略图失败'))
    }
    
    if (typeof source === 'string') {
      img.src = source
    } else if (source instanceof File) {
      generateImagePreview(source).then(url => {
        img.src = url
      }).catch(reject)
    } else {
      reject(new Error('无效的图片源'))
    }
  })
}

/**
 * 下载图片
 * @param {string} url - 图片URL
 * @param {string} filename - 文件名
 */
export function downloadImage(url, filename) {
  const link = document.createElement('a')
  link.href = url
  link.download = filename
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}

/**
 * 复制图片到剪贴板
 * @param {File|string} source - 图片文件或URL
 * @returns {Promise<void>}
 */
export async function copyImageToClipboard(source) {
  try {
    if (typeof source === 'string') {
      // URL转Blob
      const response = await fetch(source)
      const blob = await response.blob()
      
      await navigator.clipboard.write([
        new ClipboardItem({ [blob.type]: blob })
      ])
    } else if (source instanceof File) {
      await navigator.clipboard.write([
        new ClipboardItem({ [source.type]: source })
      ])
    } else {
      throw new Error('不支持的图片源类型')
    }
  } catch (error) {
    throw new Error('复制图片到剪贴板失败: ' + error.message)
  }
}

/**
 * 图片格式转换
 * @param {File} file - 原始图片文件
 * @param {string} targetType - 目标格式（如 'image/png'）
 * @param {number} quality - 质量（0-1）
 * @returns {Promise<File>}
 */
export function convertImageFormat(file, targetType = 'image/png', quality = 0.9) {
  return new Promise((resolve, reject) => {
    if (!isImage(file)) {
      reject(new Error('文件不是有效的图片格式'))
      return
    }
    
    const canvas = document.createElement('canvas')
    const ctx = canvas.getContext('2d')
    const img = new Image()
    
    img.onload = () => {
      canvas.width = img.width
      canvas.height = img.height
      ctx.drawImage(img, 0, 0)
      
      canvas.toBlob((blob) => {
        if (blob) {
          const ext = targetType.split('/')[1] || 'png'
          const baseName = file.name.replace(/\.[^/.]+$/, '')
          const newFile = new File([blob], `${baseName}.${ext}`, {
            type: targetType,
            lastModified: Date.now()
          })
          resolve(newFile)
        } else {
          reject(new Error('格式转换失败'))
        }
      }, targetType, quality)
    }
    
    img.onerror = () => {
      reject(new Error('图片加载失败'))
    }
    
    generateImagePreview(file).then(url => {
      img.src = url
    }).catch(reject)
  })
}

/**
 * 图片工具类
 */
export class ImageUtils {
  /**
   * 批量生成预览
   */
  static async generatePreviews(files) {
    const previews = []
    
    for (const file of files) {
      try {
        const preview = await generateImagePreview(file)
        previews.push({ file, preview, success: true })
      } catch (error) {
        previews.push({ file, preview: null, success: false, error })
      }
    }
    
    return previews
  }
  
  /**
   * 批量压缩图片
   */
  static async compressImages(files, options = {}) {
    const compressed = []
    
    for (const file of files) {
      try {
        const compressedFile = await compressImage(file, options)
        compressed.push({ 
          original: file, 
          compressed: compressedFile, 
          success: true 
        })
      } catch (error) {
        compressed.push({ 
          original: file, 
          compressed: null, 
          success: false, 
          error 
        })
      }
    }
    
    return compressed
  }
  
  /**
   * 批量创建缩略图
   */
  static async createThumbnails(sources, options = {}) {
    const thumbnails = []
    
    for (const source of sources) {
      try {
        const thumbnail = await createThumbnail(source, options)
        thumbnails.push({ source, thumbnail, success: true })
      } catch (error) {
        thumbnails.push({ source, thumbnail: null, success: false, error })
      }
    }
    
    return thumbnails
  }
}

export default {
  SUPPORTED_IMAGE_TYPES,
  IMAGE_MIME_TYPES,
  isImage,
  getFileExtension,
  validateImageType,
  validateImageSize,
  formatFileSize,
  generateImagePreview,
  getImageInfo,
  compressImage,
  validateImages,
  createThumbnail,
  downloadImage,
  copyImageToClipboard,
  convertImageFormat,
  ImageUtils
}
